package org.alvin.ocpp.server;

import com.google.common.collect.Maps;
import eu.chargetime.ocpp.feature.profile.ServerCoreProfile;
import eu.chargetime.ocpp.model.Request;
import eu.chargetime.ocpp.model.core.*;
import eu.chargetime.ocpp.model.localauthlist.AuthorizationData;
import eu.chargetime.ocpp.model.localauthlist.GetLocalListVersionRequest;
import eu.chargetime.ocpp.model.localauthlist.SendLocalListRequest;
import eu.chargetime.ocpp.model.localauthlist.UpdateType;
import eu.chargetime.ocpp.model.remotetrigger.TriggerMessageRequest;
import eu.chargetime.ocpp.model.remotetrigger.TriggerMessageRequestType;
import eu.chargetime.ocpp.model.reservation.CancelReservationRequest;
import eu.chargetime.ocpp.model.reservation.ReserveNowRequest;
import eu.chargetime.ocpp.model.smartcharging.GetCompositeScheduleRequest;
import eu.chargetime.ocpp.model.smartcharging.SetChargingProfileRequest;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Map;
import java.util.Set;


public class SimuatorService {

    private Map<String, Method> methodMap = Maps.newHashMap();

    public SimuatorService() {
        Method[] methods = this.getClass().getDeclaredMethods();
        for (Method method : methods) {
            //只加载私有方法
            if (method.getModifiers() == Modifier.PRIVATE) {
                methodMap.put(method.getName(), method);
            }
        }
    }

    public Set<String> getCmds() {
        return this.methodMap.keySet();
    }

    public Request createDefaultRequest(ServerCoreProfile core, String cmd) throws InvocationTargetException, IllegalAccessException {
        Method method = this.methodMap.get(cmd);
        return (Request) method.invoke(this, core);
    }
    //  模拟协议----------------

    private GetConfigurationRequest getConfiguration(ServerCoreProfile core) {
        GetConfigurationRequest request = core.createGetConfigurationRequest();
        return request;
    }

    private ClearCacheRequest clearCache(ServerCoreProfile core) {
        ClearCacheRequest request = core.createClearCacheRequest();
        return request;
    }

    private ChangeAvailabilityRequest changeAvailability_Operative(ServerCoreProfile core){
        ChangeAvailabilityRequest request = core.createChangeAvailabilityRequest(AvailabilityType.Operative ,1);
        return request;
    }

    private ChangeAvailabilityRequest changeAvailability_Inoperative(ServerCoreProfile core){
        ChangeAvailabilityRequest request = core.createChangeAvailabilityRequest(AvailabilityType.Inoperative ,1);
        return request;
    }

    private ResetRequest reset_Hard(ServerCoreProfile core){
        ResetRequest request = core.createResetRequest(ResetType.Hard);
        return request;
    }

    private ResetRequest reset_Soft(ServerCoreProfile core){
        ResetRequest request = core.createResetRequest(ResetType.Soft);
        return request;
    }

    private TriggerMessageRequest triggerMessage_BootNotification (ServerCoreProfile core){
        TriggerMessageRequest request = new TriggerMessageRequest();
        request.setRequestedMessage(TriggerMessageRequestType.BootNotification);
        request.setConnectorId(1);
        return request;
    }

    private TriggerMessageRequest triggerMessage_StatusNotification (ServerCoreProfile core){
        TriggerMessageRequest request = new TriggerMessageRequest();
        request.setRequestedMessage(TriggerMessageRequestType.StatusNotification);
        request.setConnectorId(1);
        return request;
    }

    private TriggerMessageRequest triggerMessage_Heartbeat (ServerCoreProfile core){
        TriggerMessageRequest request = new TriggerMessageRequest();
        request.setRequestedMessage(TriggerMessageRequestType.Heartbeat);
        request.setConnectorId(1);
        return request;
    }

    private TriggerMessageRequest triggerMessage_MeterValues (ServerCoreProfile core){
        TriggerMessageRequest request = new TriggerMessageRequest();
        request.setRequestedMessage(TriggerMessageRequestType.MeterValues);
        request.setConnectorId(1);
        return request;
    }

    private  UnlockConnectorRequest unlockConnector(ServerCoreProfile core){
        UnlockConnectorRequest request = core.createUnlockConnectorRequest(1);
        return request;
    }

    private SendLocalListRequest sendLocalList(ServerCoreProfile core){
        SendLocalListRequest request = new SendLocalListRequest();
        request.setListVersion(1);
        request.setUpdateType(UpdateType.Full);

        IdTagInfo idTagInfo = new IdTagInfo();
        idTagInfo.setStatus(AuthorizationStatus.Accepted);
        idTagInfo.setParentIdTag("DEF456");

        LocalDateTime time = ChronoUnit.YEARS.addTo(LocalDateTime.now(), 1);
        idTagInfo.setExpiryDate(time.atZone(ZoneId.systemDefault()));

        AuthorizationData authorizationData = new AuthorizationData();
        authorizationData.setIdTag("000064f0");
        authorizationData.setIdTagInfo(idTagInfo);
        AuthorizationData [] authorizationDatas = new AuthorizationData[]{authorizationData};
        request.setLocalAuthorizationList(authorizationDatas);
        return request;
    }


    private SetChargingProfileRequest  setChargingProfile(ServerCoreProfile core){
        SetChargingProfileRequest request = new SetChargingProfileRequest();
        request.setConnectorId(1);

        ChargingProfile chargingProfile = new ChargingProfile();
        chargingProfile.setChargingProfileId(101);
        chargingProfile.setStackLevel(1);
        chargingProfile.setChargingProfilePurpose(ChargingProfilePurposeType.TxProfile);
        chargingProfile.setRecurrencyKind(RecurrencyKindType.Daily);

        LocalDateTime time = ChronoUnit.YEARS.addTo(LocalDateTime.now(), -1);
        chargingProfile.setValidFrom(time.atZone(ZoneId.systemDefault()));
        time = ChronoUnit.YEARS.addTo(LocalDateTime.now(), 1);
        chargingProfile.setValidTo(time.atZone(ZoneId.systemDefault()));

        //
        ChargingSchedule chargingSchedule = new ChargingSchedule();
        chargingSchedule.setDuration(3600);
        chargingSchedule.setStartSchedule(LocalDateTime.now().atZone(ZoneId.systemDefault()));
        chargingSchedule.setChargingRateUnit(ChargingRateUnitType.W);

        ChargingSchedulePeriod chargingSchedulePeriod = new ChargingSchedulePeriod();
        chargingSchedulePeriod.setStartPeriod(0);
        chargingSchedulePeriod.setLimit(Double.valueOf(11000));
        chargingSchedulePeriod.setNumberPhases(3);

        chargingSchedule.setChargingSchedulePeriod(new ChargingSchedulePeriod[]{chargingSchedulePeriod});
        chargingProfile.setChargingSchedule(chargingSchedule);

        request.setCsChargingProfiles(chargingProfile);
//        {
//            "connectorId": 1,
//                "csChargingProfiles": {
//            "chargingProfileId": 101,
//                    "stackLevel": 1,
//                    "chargingProfilePurpose": "TxProfile",
//                    "chargingProfileKind": "Relative",
//                    "recurrencyKind": "Daily",
//                    "validFrom": "2024-06-25T00:00:00Z",
//                    "validTo": "2024-12-31T23:59:59Z",
//                    "chargingSchedule": {
//                "duration": 3600,
//                        "startSchedule": "2024-05-23T00:00:00Z",
//                        "chargingRateUnit": "W",
//                        "chargingSchedulePeriod": [
//                {
//                    "startPeriod": 0,
//                        "limit": 11000,
//                        "numberPhases": 3
//                }
//      ]
//            }
//        }
//        }
        return request;
    }


    private ReserveNowRequest reserveNow(ServerCoreProfile core){
        ReserveNowRequest request = new ReserveNowRequest();

        //        "connectorId": 1,
        //                "expiryDate": "2024-08-12T14:30:00Z",
        //                "idTag": "000064f0",
        //                "parentIdTag": "DEF456"

        request.setConnectorId(1);
        LocalDateTime time = ChronoUnit.YEARS.addTo(LocalDateTime.now(), 1);
        request.setExpiryDate(time.atZone(ZoneId.systemDefault()));
        request.setIdTag("000064f0");
        request.setParentIdTag("DEF456");
        return request;
    }

    private CancelReservationRequest cancelReservation (ServerCoreProfile core){
        CancelReservationRequest request = new CancelReservationRequest();
        request.setReservationId(12345);
        return request;
    }

    private GetCompositeScheduleRequest compositeSchedule(ServerCoreProfile core){
        GetCompositeScheduleRequest request = new GetCompositeScheduleRequest();
        request.setConnectorId(1);
        request.setDuration(3600);
        request.setChargingRateUnit(eu.chargetime.ocpp.model.smartcharging.ChargingRateUnitType.W);
        return request;
    }

    private RemoteStopTransactionRequest remoteStopTransaction(ServerCoreProfile core){
        RemoteStopTransactionRequest request = new RemoteStopTransactionRequest();
        request.setTransactionId(12345);
        return request;
    }

    private ChangeConfigurationRequest changeConfiguration(ServerCoreProfile core){
        ChangeConfigurationRequest request = new ChangeConfigurationRequest();
        request.setKey("HeartbeatInterval");
        request.setValue("120");
        return request;
    }

    private GetLocalListVersionRequest getLocalListVersion(ServerCoreProfile core){
        GetLocalListVersionRequest request = new GetLocalListVersionRequest();
        return request;
    }


    private RemoteStartTransactionRequest remoteStartTransaction(ServerCoreProfile core){
        RemoteStartTransactionRequest request =core.createRemoteStartTransactionRequest("ozge_4M");
        request.setConnectorId(1);
        return request;
    }




}
